package handler

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/360EntSecGroup-Skylar/excelize"
	"github.com/gin-gonic/gin"
	model2 "gomicrodemo/changgou-api-gateway/user/model"
	"gomicrodemo/common"
	"gomicrodemo/proto/rand"
	"gomicrodemo/proto/user"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"strconv"
	"time"
)

type User_APIHandler struct {
	randClient rand.RandService
	userClient user.UserService
}

//handler相当于grpc里面的controller
func GetUserAPIHandler(randService rand.RandService, userService user.UserService) *User_APIHandler {
	return &User_APIHandler{
		userClient: userService,
		randClient: randService,
	}
}

func (h User_APIHandler) Rand_POST(c *gin.Context) {
	common.Print_RequestId(c)
	//绑定参数到request
	request := &rand.RandRequest{}
	c.ShouldBindJSON(&request)

	//调用rpc服务
	response, err := h.randClient.GetRand(c, request)
	if err != nil {
		log.Println(err)
	}

	username, _ := c.Get("username")
	//使用gin框架返回结果值
	c.JSON(http.StatusOK, gin.H{
		"data":      response.Result,
		"username":  username,
		"RequestId": common.Print_RequestId(c),
	})
	return
}

func (h User_APIHandler) UserRegistry(c *gin.Context) {
	common.Print_RequestId(c)
	request := &user.UserRegistryRequest{}
	c.ShouldBindJSON(&request)

	//调用user的rpc服务
	response, err := h.userClient.UserRegistry(c, request)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"Code":      -1,
			"Msg":       response.Message,
			"RequestId": common.Print_RequestId(c),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"data":      response,
		"RequestId": common.Print_RequestId(c),
	})
	return
}

func (h User_APIHandler) UserLogin(c *gin.Context) {
	common.Print_RequestId(c)
	//获取请求参数,绑定参数
	request := &user.UserLoginRequest{}
	c.ShouldBindJSON(request)

	////获取redis中的验证码
	//rdb := common.GetRedisDB()
	//Verification_code := rdb.Get(c, "code")
	//
	//if Verification_code.Val() != request.Checkcode {
	//	c.JSON(500, gin.H{
	//		"data": "验证码错误",
	//	})
	//	return
	//}

	//调用user的rpc服务
	response, err := h.userClient.UserLogin(c, request)
	if err != nil {
		log.Panicf("调用user的rpc服务失败，失败原因：", err)
		c.JSON(http.StatusOK, gin.H{
			"Code":      -1,
			"Msg":       response.Message,
			"RequestId": common.Print_RequestId(c),
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"data":      response,
		"RequestId": common.Print_RequestId(c),
	})
	return
}

func (h User_APIHandler) UserExport(c *gin.Context) {
	common.Print_RequestId(c)
	//校验参数
	var (
		req model2.UserExport
		rsp *user.UserExportResponse
		err error
	)
	if err = c.ShouldBindJSON(&req); err != nil {
		log.Printf("ShouldBindJson fail, msg:%v", err)
		c.JSON(500, gin.H{
			"error":     err,
			"RequestId": common.Print_RequestId(c),
		})
		return
	}

	//调用微服务获取用户列表
	request := &user.UserExportRequest{
		Limit:    req.Limit,
		Offset:   req.Offset,
		Datetime: req.Datetime,
	}
	rsp, err = h.userClient.UserExport(c, request)
	if rsp.Users == nil {
		log.Printf("UserExport fail, msg:%v", err)
		c.JSON(200, gin.H{
			"error":     err,
			"RequestId": common.Print_RequestId(c),
		})
		return
	}
	if err != nil {
		log.Printf("UserExport fail, msg:%v", err)
		c.JSON(500, gin.H{
			"error":     err,
			"RequestId": common.Print_RequestId(c),
		})
		return
	}

	//获取xlsx文件对象、文件名
	file, filename := downloadUserExport(rsp)

	//设置响应头
	c.Header("Content-Type", "application/octet-stream")
	c.Header("Content-Disposition", "attachment; filename="+filename)
	c.Header("Content-Transfer-Encoding", "binary")
	//写出到write中返回给客户端
	_ = file.Write(c.Writer)
}

//将文件上传到本地服务器，
func (h User_APIHandler) UploadUserForm(c *gin.Context) {
	common.Print_RequestId(c)
	//调用微服务获取用户列表
	request := &user.UserExportRequest{
		Limit:    10,
		Offset:   0,
		Datetime: "1624198666",
	}
	rsp, err := h.userClient.UserExport(c, request)
	if err != nil {
		log.Printf("UserExport fail msg:%v", err.Error())
	}

	//获取用户数据的文件对象File和文件名
	file, filename := downloadUserExport(rsp)
	//byte,err := ioutil.ReadFile(filename)
	//获取一个读取文件缓存区的Reader
	buffer1, err := file.WriteToBuffer()
	filebyte := buffer1.Bytes()
	reader := bytes.NewReader(filebyte)

	//获取一个写入到空buffer的Writer写入流
	buffer := bytes.Buffer{}
	writer := multipart.NewWriter(&buffer) //传入指针
	fh, _ := writer.CreateFormFile("homin_file", filename)
	//将缓冲区中的文件数据拷贝到空buffer中
	io.Copy(fh, reader)
	writer.Close()

	http_request, _ := http.NewRequest("POST", "http://127.0.0.1:9333/submit", &buffer)
	http_request.Header.Add("content-type", writer.FormDataContentType())
	resp, _ := http.DefaultClient.Do(http_request)

	respbyte, _ := ioutil.ReadAll(resp.Body)
	var resultmap = make(map[string]interface{})
	json.Unmarshal(respbyte, resultmap)

	fmt.Println(resultmap)
	c.JSON(http.StatusOK, gin.H{
		"code":      0,
		"msg":       "success",
		"RequestId": common.Print_RequestId(c),
	})
	return
}

//生成xlsx文件
func downloadUserExport(rsp *user.UserExportResponse) (*excelize.File, string) {
	f := excelize.NewFile()
	header := []string{"用户名", "密码", "邮件", "频道", "昵称", "创建时间", "更新时间"}
	index := f.NewSheet("Sheet1")
	f.SetSheetRow("Sheet1", "A1", &header)

	//将数据填充到每一行
	for k, rowdata := range rsp.Users {
		f.SetSheetRow("Sheet1", "A"+strconv.Itoa(k+2), &[]interface{}{
			rowdata.Username,
			rowdata.Password,
			rowdata.Email,
			rowdata.Channel,
			rowdata.Nickname,
			rowdata.CreatedAt,
			rowdata.UpdateAt,
		})
	}
	f.SetActiveSheet(index)
	f.Save()
	filename := time.Now().Format("2006-01-02") + "_Users.xlsx"

	//返回文件对象和文件名
	return f, filename
}
